package model

import (
	"database/sql/driver"
	"encoding/json"
	"strconv"
	"time"
)

const (
	UploadStatusPending    = iota
	UploadStatusProcessing = iota
	UploadStatusCompleted  = iota
	UploadStatusFailed     = iota
)

// UploadIDString 用于 JSON 序列化，将大整数转换为字符串以避免 JavaScript 精度丢失
// 注意：数据库存储仍使用 int64（BIGINT），只有 JSON 序列化/反序列化时使用字符串
type UploadIDString int64

// MarshalJSON 实现 JSON 序列化，将 int64 转换为字符串（用于前端传输）
func (u UploadIDString) MarshalJSON() ([]byte, error) {
	return json.Marshal(strconv.FormatInt(int64(u), 10))
}

// UnmarshalJSON 实现 JSON 反序列化，将字符串解析为 int64（从前端接收）
func (u *UploadIDString) UnmarshalJSON(data []byte) error {
	var s string
	if err := json.Unmarshal(data, &s); err != nil {
		// 如果不是字符串，尝试作为数字解析（向后兼容）
		var i int64
		if err2 := json.Unmarshal(data, &i); err2 != nil {
			return err
		}
		*u = UploadIDString(i)
		return nil
	}
	val, err := strconv.ParseInt(s, 10, 64)
	if err != nil {
		return err
	}
	*u = UploadIDString(val)
	return nil
}

// Value 实现 driver.Valuer 接口，用于 GORM 写入数据库时转换为 int64
func (u UploadIDString) Value() (driver.Value, error) {
	return int64(u), nil
}

// Scan 实现 sql.Scanner 接口，用于 GORM 从数据库读取时从 int64 转换
func (u *UploadIDString) Scan(value interface{}) error {
	if value == nil {
		*u = 0
		return nil
	}
	switch v := value.(type) {
	case int64:
		*u = UploadIDString(v)
		return nil
	case int:
		*u = UploadIDString(v)
		return nil
	case string:
		// 某些驱动可能返回字符串
		val, err := strconv.ParseInt(v, 10, 64)
		if err != nil {
			return err
		}
		*u = UploadIDString(val)
		return nil
	}
	return nil
}

type UploadTask struct {
	UploadID       UploadIDString `gorm:"primaryKey;column:upload_id;type:bigint" json:"upload_id"`  // 主键，前端唯一标识（JSON 字符串，数据库 int64）
	FileName       string         `gorm:"type:varchar(255);not null" json:"file_name"`               // 原始文件名
	FileSize       int64          `gorm:"not null" json:"file_size"`                                 // 文件大小（字节）
	MimeType       string         `gorm:"type:char(32)" json:"mime_type"`                            // MIME 类型
	ChunkSize      int            `gorm:"not null" json:"chunk_size"`                                // 每个分片大小（字节）
	TotalChunks    int            `gorm:"not null" json:"total_chunks"`                              // 总分片数
	UploadedChunks int            `gorm:"default:0" json:"uploaded_chunks"`                          // 已上传数量
	IsComplete     bool           `gorm:"default:false" json:"is_complete"`                          // 是否合并完成
	StreamingHash  string         `gorm:"column:streaming_hash;type:char(32)" json:"streaming_hash"` // 流式 hash（已上传分片的 MD5，最终结果）
	MD5State       string         `gorm:"column:md5_state;type:text" json:"-"`                       // MD5 内部状态（序列化后的上下文）
	OwnerID        *int64         `gorm:"column:owner_id" json:"owner_id"`                           // 上传者，可为空
	CreatedAt      time.Time      `gorm:"autoCreateTime" json:"created_at"`                          // 创建时间
	UpdatedAt      time.Time      `gorm:"autoUpdateTime" json:"updated_at"`                          // 更新时间
}

func (UploadTask) TableName() string {
	return "upload_task"
}

type UploadChunk struct {
	ID         int64     `gorm:"primaryKey;autoIncrement"`
	UploadID   int64     `gorm:"not null;index"`     // 所属任务
	ChunkIndex int       `gorm:"not null"`           // 第几个分片，从 0 开始
	ChunkSize  int       `gorm:"not null"`           // 实际分片大小
	ChunkMD5   string    `gorm:"type:text"`          // 可选：校验码
	StorageKey string    `gorm:"type:text;not null"` // 存储路径或唯一标识
	Status     int       `gorm:"type:int"`           // 上传状态
	CreatedAt  time.Time `gorm:"autoCreateTime"`     // 创建时间
	UploadedAt time.Time `gorm:"autoCreateTime"`     // 上传时间（可等同创建）
}

func (UploadChunk) TableName() string {
	return "upload_chunk"
}
